-- CALC_DUNGEON_ELEMENT_ATTRIB
-- 计算地牢元素的基础属性

------------------------------------------------
-- 计算地牢格子元素的基本属性
-- @param dungeonId     地牢区域
-- @param element       格子元素，对应dungeon_elemen表的配置
-- @param layer         层数
-- @param pos           位置
return function(dungeonId, element, layer, pos)
    -- 获取配置的参数
    local args  = table.deepcopy(DungeonM.queryElement(element, "args"));
    local dbase = table.deepcopy(DungeonM.queryElement(element, "dbase"));
    local class = DungeonM.queryElement(element, "class");
    -- 覆盖了函数，将type修改为typ
    local typ  = DungeonM.query(class, "type");
    local rand1 = DungeonM.getRandSeed("DUNGEON_ELEMENT") % 1000;
    local rand2 = DungeonM.getRandSeed("DUNGEON_ELEMENT") % 100;
    local rand3 = DungeonM.getRandSeed("DUNGEON_ELEMENT");
    if dungeonId == nil then
        dungeonId = user.dbase:query("currentDungeon");
    end
    local layerFix = DungeonAreaM.query(dungeonId, "layer_fix");
    local ret = {};
    local fix_co;
    local sp;
    local arr_food;
    local prop;
    local simple = false;
    local rate1;
    local rate2;
    local rate3;
    local arr;

    if FormulaM.invoke("CAN_BONUS_SIMPLE_ITEM", dungeonId, layer) then
        -- 产出简单有用物品
        simple = true;
    end

    -- 这里面的顺序和服务器的需要严格一致(因为需要用到随机数)
    if typ == GRID_TYPE_SHOP then
        -- TODO: 商店，抽取商品
        ret.goods = DungeonShopM.fetchDungeonGoods(args.shop_type, pos);
        ret.shopType = args.shop_type;
    elseif typ == GRID_TYPE_BANK then
        -- 银行
        -- 重置兑换次数
        DungeonBankM.resetExchangeTimes(layer);
    elseif typ == GRID_TYPE_MONSTER then
        -- 怪物
        ret.class_id = dbase.class_id;

        -- 如果怪物有掉落
        if args.drop_rate then
            local rate = args.drop_rate;

            -- 物品掉落概率增加（duneon_element相应掉落增加drop_type字段）
            prop = PropM.combine(ME.user, "drop_rate1", args.drop_type);

            rate = PropM.apply(prop, rate);

            if rand2 < rate then
                if type(args.bonus[1]) == 'table' then
                    local bonusArgs = args["bonus"];
                    arr = fetchElemBySeed(bonusArgs, rand3);
                    ret.bonus = {1, arr["class_id"], arr["amount"]};
                elseif type(args.bonus[2]) == 'table' and type(args.bonus[1]) == 'number' then
                    fix_co = args.bonus[3];
                    arr    = args.bonus[2];
                    ret.bonus = {1, arr[1 + rand3 % #arr], fix_co};
                else
                    ret.bonus = args.bonus;
                end
            end
        elseif args.bonus then
            -- 没有配置掉落概率就默认是100%的
            ret.bonus = args.bonus;
        end

        -- 掉落转变成其他
        if ret.bonus and dbase.drop_change then
            local rate = dbase.drop_change["rate"];
            local bonus = dbase.drop_change["bonus"];

            local p = PropM.combine(ME.user, "drop_rate", bonus[2]);
            rate = PropM.apply(p, rate);
            if (rand3 % 100) < rate then
                ret.bonus = bonus;
            end
        end

        if dbase.bonus_arg then
            ret.bonusArg = dbase.bonus_arg;
        end

        -- 有开启回合
        if dbase.open_round then
            ret.openRound = dbase.open_round;
        end
    elseif typ == GRID_TYPE_BOSS then
        -- BOSS
        local m = {};
        ret = table.add(args, m);
    elseif typ == GRID_TYPE_ITEM then
        -- 没有bonus数据？
        if not args.bonus then
            ret = table.add(args, dbase);
        -- 魔法卷轴
        elseif args.bonus[2] == "spell" then
            if type(dbase["class_id"]) == 'number' then
                -- 如果传入了编号，直接使用
                ret.bonus = { 1, dbase["class_id"], 1 };
            else
                local rank;
                if rand1 < 100 then
                    rank = 3;
                elseif rand1 < 400 then
                    rank = 2;
                else
                    rank = 1;
                end

                if not FormulaM.invoke("CAN_BONUS_ADV_SPELL", dungeonId, layer) then
                    -- 不能产出高级卷轴
                    rank = math.min(rank, 2);
                end

                local scroll = ItemM.getScrollByRank(rank, simple);
                local index = rand3 % #scroll + 1;
                local scrollId = scroll[index];

                ret.bonus = {1, scrollId, 1,};
            end

        -- 探索点
        elseif args.bonus[2] == "search_point" then
            fix_co = args.bonus[3];
            sp = FormulaM.invoke("CALC_SEARCH_POINT_COST", fix_co, layer, layerFix);
            ret.bonus = {2, "search_point", sp};
        -- 金钱
        elseif args.bonus[2] == "money" then
            fix_co = args.bonus[3] * 2;
            ret.bonus = {2, "money", fix_co};
        -- 血瓶
        elseif args.bonus[2] == "hp" or args.bonus[2] == "limit_hp" then
            fix_co = args.bonus[3];
            fix_co = math.modf((5 * fix_co + layer ) * (60 + layerFix) / 300);

            -- 血瓶效果+%
            prop   = PropM.combine(ME.user, "bottles_effect", "hp");
            fix_co = PropM.apply(prop, fix_co);

            ret.bonus = {2, args.bonus[2], fix_co};
        -- 蓝瓶
        elseif args.bonus[2] == "mp" or args.bonus[2] == "limit_mp" then
            fix_co = args.bonus[3];

            -- 魔瓶效果+%
            prop = PropM.combine(ME.user, "bottles_effect", "mp");
            fix_co = PropM.apply(prop, fix_co);

            ret.bonus = {2, args.bonus[2], fix_co};
        -- 食材
        elseif type(args.bonus[2]) == 'table' then
            fix_co = args.bonus[3];
            arr_food = args.bonus[2];
            ret.bonus = {1, arr_food[1 + rand3 % #arr_food], fix_co};
        -- 装备
        elseif args.bonus[2] == "equip" then
            if type(dbase["class_id"]) == 'number' then
                -- 如果传入了编号，直接使用
                ret.bonus = { 1, dbase["class_id"], 1 };
            else
                ret = args;
            end
        else
            ret = args;
        end

        if args.bonus_arg then
            ret.bonusArg = args.bonus_arg;
        end
    elseif typ == GRID_TYPE_SLIME then
        -- TODO: 解救slime

        -- 该层可解救的slime
        local classId = DungeonAreaM.query(dungeonId, "slime")[layer];

        if classId then
            -- 奖励一个英雄（如果已经有该英雄，则转化为徽章碎片，BonusM中处理）
            ret.bonus = { 3, classId, 1, };
        else
            -- 把dbase也弄进来
            ret = table.add(args, dbase);
        end
    elseif typ == GRID_TYPE_BOX then
        -- 宝箱
        -- 每   3层奖励：铜宝箱（随机1、2、3级宝物 6:3:1）、铜卷轴（随机1~2本3级卷轴）
        -- 每   5层奖励：银宝箱（不给宝物）、银卷轴（随机2个卷轴4、5级卷轴 3:2）
        -- 每  10层奖励：金宝箱（随机3、4、5级宝物 9:8:3）、金卷轴（不给卷轴）
        -- 每  50层奖励：神宝箱（随机5级宝物）
        -- 每 100层奖励：神圣宝箱（随机6级宝物）
        -- 配置表中的奖励内容是无效的，需要在这里单独计算
        local boxType = args.box_type;
        ret.boxType = boxType;
        local equipTable;
        local scrollTable;
        local rank;
        local arr1;
        local amount;

        if boxType == "copper" then
            -- 铜宝箱
            if rand1 < 500 then
                -- 随机1、2、3级宝物 6:3:1
                rate1 = 60;
                rate2 = 30;
                rate3 = 10;
                -- 增加高级宝物的属性
                prop = PropM.combine(ME.user, "better_equip", 1);
                rate2 = PropM.apply(prop,rate2);
                rate3 = PropM.apply(prop,rate3);
                rate1 = 100 - rate2 - rate3;

                if rand2 < rate1 then
                    rank = 1;
                elseif rand2 < rate1 + rate2 then
                    rank = 2;
                else
                    rank = 3;
                end
                equipTable = ItemM.getEquipByRank(rank, simple);
                ret.bonus = { 1, FormulaM.invoke("FETCH_BY_RAND", equipTable, rand3), 1, };
            else
                -- 随机3级卷轴
                rank = 3;
                if not FormulaM.invoke("CAN_BONUS_ADV_SPELL", dungeonId, layer) then
                    -- 不能产出高级卷轴
                    rank = 2;
                end
                arr1 = { { ["amount"] = 1, ["ratio"] = 100, }, { ["amount"] = 2, ["ratio"] = 100, }, };
                amount = fetchElemBySeed(arr1, rand3)["amount"];
                scrollTable = ItemM.getScrollByRank(rank, simple);
                ret.bonus = ({ 1, FormulaM.invoke("FETCH_BY_RAND", scrollTable, rand3), amount, });
            end
        elseif boxType == "silver" then
            -- 银宝箱
            -- 随机4、5级卷轴，概率3:2，数量1~3本
            rate1 = 60;
            rate2 = 40;
            -- 增加高级卷轴的属性
            prop = PropM.combine(ME.user, "better_scroll", 1);
            rate2 = PropM.apply(prop,rate2);
            rate1 = 100 - rate2;
            if rand2 < rate1 then
                rank = 4;
            else
                rank = 5;
            end

            if not FormulaM.invoke("CAN_BONUS_ADV_SPELL", dungeonId, layer) then
                -- 不能产出高级卷轴
                rank = math.min(rank, 2);
            end

            if ActivityDungeonM.isActivityDungeon(dungeonId) then
                -- 活动副本不能产出5阶卷轴
                rank = math.min(rank, 4);
            end

            arr1 = { { ["amount"] = 1, ["ratio"] = 100, }, { ["amount"] = 2, ["ratio"] = 100, }, };
            amount = fetchElemBySeed(arr1, rand3)["amount"];
            scrollTable = ItemM.getScrollByRank(rank, simple);
            if rank == 5 then
                ret.bonus = ({ 1, FormulaM.invoke("FETCH_BY_RAND", scrollTable, rand3), 1, });
            else
                ret.bonus = ({ 1, FormulaM.invoke("FETCH_BY_RAND", scrollTable, rand3), amount, });
            end
        elseif boxType == "golden" then
            -- 金宝箱
            -- 随机3、4、5级别宝物 9:8:3
            rate1 = 45;
            rate2 = 40;
            rate3 = 15;
            -- 增加高级宝物的属性
            prop = PropM.combine(ME.user, "better_equip", 1);
            rate2 = PropM.apply(prop,rate2);
            rate3 = PropM.apply(prop,rate3);
            rate1 = 100 - rate2 - rate3;

            if rand2 < rate1 then
                equipTable = ItemM.getEquipByRank(3, simple);
                ret.bonus = { 1, FormulaM.invoke("FETCH_BY_RAND", equipTable, rand3), 1, };
            elseif rand2 < rate1 + rate2 then
                equipTable = ItemM.getEquipByRank(4, simple);
                ret.bonus = { 1, FormulaM.invoke("FETCH_BY_RAND", equipTable, rand3), 1, };
            else
                equipTable = ItemM.getEquipByRank(5, simple);
                ret.bonus = { 1, FormulaM.invoke("FETCH_BY_RAND", equipTable, rand3), 1, };
            end
        elseif boxType == "darkgoldenrod" then
            -- 神宝箱
            -- 随机5级宝物
            equipTable = ItemM.getEquipByRank(5, simple);
            ret.bonus = { 1, FormulaM.invoke("FETCH_BY_RAND", equipTable, rand3), 1, };
        elseif boxType == "holy" then
            -- 神圣宝箱
            -- 随机6级宝物
            equipTable = ItemM.getEquipByRank(6, simple);
            ret.bonus = { 1, FormulaM.invoke("FETCH_BY_RAND", equipTable, rand3), 1, };
        else
            ret.bonus = args.bonus;
        end
    elseif typ == GRID_TYPE_FOUNTAIN then
        -- 幸运喷泉
        -- 生成幸运喷泉奖励
        ret.bonus = DungeonFountainM.generateBonus();
    elseif typ == GRID_TYPE_MINE then
        -- 矿脉
        -- 生成矿脉奖励
        ret.bonus = DungeonMineM.generateMineBonus();
    elseif typ == GRID_TYPE_INSTANCE then
        -- 地牢副本
        ret.instanceId = DungeonInstanceM.fetchInstanceId(args);
    elseif typ == GRID_TYPE_BOSS_BOX then
        -- BOSS宝箱
        ret.bonus = FormulaM.invoke("CALC_BOSS_BOX_BONUS", ME.user, dungeonId, element, layer);
    elseif typ == GRID_TYPE_ACTIVITY_BOSS_BOX then
        -- 活动BOSS宝箱
        ret.bonus = FormulaM.invoke("CALC_BOSS_ACTIVITY_BOX_BONUS", ME.user, dungeonId, element, layer);
    elseif typ == GRID_TYPE_BEEHIVE then
        -- 蜂巢
        ret = BeehiveM.initBeehive(args["beehive"], 0, pos);
    elseif typ == GRID_TYPE_TRAP then
        -- 陷阱
        ret = CommonTrapM.fetchTrapData(args["trap"], pos);
    elseif typ == GRID_TYPE_FRUIT then
        -- 果树
        ret = args;
    elseif typ == GRID_TYPE_GARDEN then
        -- 魔藤/花园
        ret = BineM.initGardenData(pos);
    elseif typ == GRID_TYPE_VILLAGER then
        -- 村民
        ret = args;
    elseif typ == GRID_TYPE_TREASURE then
        -- 宝藏
        ret = args;
    elseif typ == GRID_TYPE_LAB then
        -- 死灵实验台
        ret.labId = DungeonLabM.fetchLabId();
    elseif typ == GRID_TYPE_STONE then
        -- 石柱
        ret.id = MagicStoneM.fetchStone(pos);
    elseif typ == GRID_TYPE_INTERFERE_DEVICE then
        -- 电流干扰装置
        ret.id = MagicStoneM.fetchStone(pos, args["stone_id"]);
    elseif typ == GRID_TYPE_MINE_HILL then
        -- 矿山
        ret = MineHillM.fetchMineData(args, rand1);
    elseif typ == GRID_TYPE_DRIFT_BOTTLE then
        -- 漂流瓶
        ret = args;
        -- 能说话的抽取一下
        if dbase["can_talk"] == 1 then
            ret.id = DriftBottleM.fetchBottleId();
        end
    elseif typ == GRID_TYPE_OLD_TV then
        -- 老式电视机
        ret.bonus = AdM.fetchDungeonTvBonus();

    elseif typ == GRID_TYPE_SPHINX then
        -- 狮身人面像
        local riddleId = ME.user.dbase:query("sphinx_riddle", 0);
        local total = #table.keys(RiddleM.query(args["riddle_class"]));
        if riddleId <= 0 then
            riddleId = rand1 % total + 1;
        end

        local next = riddleId % total + 1;

        -- 下次谜语id
        ME.user.dbase:set("sphinx_riddle", next);

        ret = table.add({["riddle_id"] = riddleId, }, args);
    elseif typ == GRID_TYPE_UNREAL_DUNGEON then
        -- 夹层迷宫
        ret.unrealId = args.unreal_id;
    elseif typ == GRID_TYPE_DESERT_ALTAR then
        -- 沙漠祭坛，交给模块抽取数据
        ret = DesertAltarM.fetchAltarData();
    elseif typ == GRID_TYPE_BOOKSHELF then
        -- 废弃的书架
        local bonus_info = args["bonus"];

        if type(bonus_info) == "table" then
            ret.bonus = bonus_info;
        else
           ret = args;
        end
    elseif typ == GRID_TYPE_DEMON_STATUE then
        -- 魔神雕像
        ret = table.add(DemonStatueM.initStatueData(), args);
    elseif typ == GRID_TYPE_COFFIN then
        -- 圣棺
        local bonus_info = args["bonus"];

        if type(bonus_info) == "table" then
            ret.bonus = bonus_info;
        else
            ret.bonus = DraculaCastleM.generateCoffinBonus();
        end
    elseif typ == GRID_TYPE_ARENA then
        -- 角斗台
        ret.unrealId = args.unreal_id;
        ret = table.add(ret, ArenaM.fetchRoleData());
    elseif typ == GRID_TYPE_DARK_DRAGON then
        -- 黑暗龙雕像
        ret["sacrifice"] = args["sacrifice"];
    elseif typ == GRID_TYPE_SHADOW_SPACE then
        -- 阴影空间
        ret.unrealId = args.unreal_id;
    elseif typ == GRID_TYPE_SKY_OBJECT then
        -- 天空副本通用建筑
        if args.bonus_arg then
            ret.bonusArg = args.bonus_arg;
        else
            ret = args;
        end
    elseif typ == GRID_TYPE_DIAMON_STATUE then
        -- 钻石雕像
        local diamonStatue = DungeonBossM.query(dungeonId, "diamon_statue");
        ret["bonus"] = { 1, diamonStatue, 1, };
    elseif typ == GRID_TYPE_SPECIAL_BUILDING then
        -- 特殊建筑
        if args.bonus_arg then
            ret.bonusArg = args.bonus_arg;
            ret.bonus = args.bonus;
        else
            ret = args;
        end
    elseif typ == GRID_TYPE_SKY_LAB then
        -- 死灵实验台
        ret.labId = DungeonLabM.fetchLabId();
    elseif typ == GRID_TYPE_KRYPTONITE then
        ret.id = MagicStoneM.fetchStone(pos, 7);
    elseif typ == GRID_TYPE_CAVE_HIDE_ITEM then
        -- 洞窟隐藏物件
        -- 如果配置的是随机权重抽取
        if type(args.bonus[1]) == 'table' and type(args.bonus[1]["ratio"]) == "number" then
            local itemsArgs = args["bonus"];
            arr = fetchElemBySeed(itemsArgs, rand3);
            ret.bonus = {1, arr["class_id"], arr["amount"]};
        else
            ret = args;
        end

        ret.bonusArg = { ["class"] = class, };
        if args.bonus_arg then
            ret.bonusArg = table.add(ret.bonusArg, args.bonus_arg);
        end
    elseif typ == GRID_TYPE_SUMMON then
        -- 召唤兽
        local ret = args;
        if type(args["drop_rate"]) == "number" and args["bonus"] then
            -- 概率掉落在死亡的时候才执行
            ret.bonus = nil;
            ret.drop_rate = nil;
        end
    elseif typ == GRID_TYPE_MACHINE_PLATFORM then
        -- 作战平台
        ret = table.add(MachinePlatformM.fetchSkillId(args), args);
    elseif typ == GRID_TYPE_CHESS_TABLE then
        -- 棋桌
        ret = table.add(ChessTableM.fetchOptions(), args);
    elseif typ == GRID_TYPE_WAKUSEI then
        -- 变异体冈布奥
        ret = table.add(WakuseiM.fetchWakusei(), args);
    elseif typ == GRID_TYPE_EVIL_STATUE then
        -- 邪神雕像
        ret = table.add(EvilStatueM.initGridData(dbase), args);
    elseif typ == GRID_TYPE_AVALON_LAB then
        -- 阿瓦隆实验室
        local labType = args["lab_type"];
        ret = table.add(AvalonFortM.calcAvalonLabCost(labType), args);
    elseif typ == GRID_TYPE_TIMEBOMB then
        -- 定时炸弹
        ret = table.add(AvalonFortM.calcTimeBombVitaport(), args);
    elseif typ == GRID_TYPE_INTELLIGENCE_PC then
        -- 智能电脑
        ret = table.add(IntelligencePCM.fetchPcData(), args);
    elseif typ == GRID_TYPE_ACTIVITY_BOX then
        -- 活动宝箱
        ret = ActivityDungeonM.calcActivityBoxBonus(args);
    elseif typ == GRID_TYPE_FAIRY then
        ret = PinocchioM.fetch_fairy();
    else
        -- TODO: 其他的待定
        ret = args;

        ret.bonusArg = args["bonus_arg"];
    end

    return ret;
end
